package mrpanyu.guitool.deploy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpProgressMonitor;

import mrpanyu.guitool.base.model.Tool;

public class JSchHelper {

	private Tool tool;
	private ServerInfo serverInfo;

	public JSchHelper(Tool tool, ServerInfo serverInfo) {
		this.tool = tool;
		this.serverInfo = serverInfo;
	}

	private Session openSession() throws JSchException {
		JSch jsch = new JSch();
		Session session = jsch.getSession(serverInfo.getUsername(), serverInfo.getHost(), serverInfo.getPort());
		session.setPassword(serverInfo.getPassword());
		Properties config = new Properties();
		config.put("StrictHostKeyChecking", "no");
		session.setConfig(config);
		session.connect(10000);
		return session;
	}

	public void uploadFile(File localFile, String remotePath) throws JSchException, SftpException, IOException {
		if (!localFile.isFile()) {
			tool.errorMessage("文件不存在: " + localFile.getCanonicalPath());
			return;
		}
		Session session = openSession();
		try (FileInputStream fin = new FileInputStream(localFile)) {
			ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
			channel.connect(10000);
			long fileLength = localFile.length();
			AtomicLong uploaded = new AtomicLong(0);
			channel.put(fin, remotePath, new SftpProgressMonitor() {
				@Override
				public void init(int op, String src, String dest, long max) {
					tool.infoMessage("开始上传文件: " + remotePath);
				}

				@Override
				public void end() {
					tool.infoMessage("完成上传文件: " + remotePath);
				}

				@Override
				public boolean count(long count) {
					long lastUploadedMB = uploaded.get() / 1024 / 1024;
					long currentUploadedMB = uploaded.addAndGet(count) / 1024 / 1024;
					if (currentUploadedMB > lastUploadedMB) {
						tool.infoMessage("已上传: " + currentUploadedMB + "MB/" + (fileLength / 1024 / 1024) + "MB");
					}
					return true;
				}
			}, ChannelSftp.OVERWRITE);
			channel.exit();
		} finally {
			session.disconnect();
		}
	}

	public void executeCommands(List<String> commands) throws JSchException, IOException {
		tool.infoMessage("开始执行命令");
		Session session = openSession();
		try {
			ChannelShell channel = (ChannelShell) session.openChannel("shell");
			channel.connect(10000);
			BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInputStream(), "UTF-8"));
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(channel.getOutputStream(), "UTF-8"));
			for (String command : commands) {
				writer.println(command);
			}
			writer.println("exit");
			writer.flush();
			String line = reader.readLine();
			while (line != null) {
				tool.infoMessage("> " + line);
				line = reader.readLine();
			}
			tool.infoMessage("结束执行命令，Exit Status: " + channel.getExitStatus());
		} finally {
			session.disconnect();
		}
	}

}
